# Application configuration

> Application settings live in the developer-owned `src/supacharger.config.ts`. The CLI-managed `src/supacharger/supacharger-config.ts` is only a stable re-export and must not contain application values.

# Application configuration

Application settings live in the developer-owned `src/supacharger.config.ts`. The CLI-managed `src/supacharger/supacharger-config.ts` is only a stable re-export and must not contain application values.

Because the CLI preserves the developer file, review release notes when a core update introduces configuration keys and merge those keys deliberately.

## Metadata, root providers, and analytics

`METADATA` configures the canonical site URL, child-page title template, indexing policy, standard favicon declarations, optional social image, colour scheme, and theme colour. `ROOT_PROVIDERS` enables the standard internationalisation, theme, and toast layers while the editable root layout retains each application's concrete provider implementations. `ANALYTICS` independently configures Google Analytics and Vercel Analytics.

Use `NEXT_PUBLIC_SITE_URL` for the stable production origin and `NEXT_PUBLIC_GOOGLE_ANALYTICS_ID` for an optional GA4 measurement ID. See [SEO, document metadata, and analytics](../Marketing-and-Analytics/seo-and-analytics.md) for the complete configuration and page-level override patterns.

During first deployment, configure local and Vercel scopes through the [environment-variable wizard step](../guides/hosted-setup/03-environment-variables.md). Any `NEXT_PUBLIC_` value is sent to the browser; secret Supabase, Stripe, SMTP, and webhook credentials must remain server-only.

## Authentication session configuration

```ts
AUTH_SESSION: {
  VERIFICATION_MODE: 'claims',
  ALLOW_ANONYMOUS_USERS: false,
},
```

`claims` is the standard SSR verifier and validates the JWT signature and expiry. Use `user` only when every matched request needs a fresh Auth-server user/session check. Anonymous Supabase Auth users have the `authenticated` database role, so they remain excluded unless the application explicitly sets `ALLOW_ANONYMOUS_USERS` to true and its RLS supports them.

## Authenticated destinations

```ts
USER_REDIRECTS: {
  AUTHED_USER: {
    HOME_PATH: '/',
    AUTHGUARD_REDIRECT_DESTINATION: '/',
    LOGIN_REDIRECT_DESTINATION: '/',
  },
},
```

- `HOME_PATH` is the application's normal home destination for an authenticated user.
- `LOGIN_REDIRECT_DESTINATION` is the destination after a successful passwordless or OAuth PKCE callback. It normally matches `HOME_PATH`; applications whose `/` route is public marketing content may set both values to an authenticated route such as `/account`.
- `AUTHGUARD_REDIRECT_DESTINATION` is the destination used when an authenticated user requests an authentication page they should no longer see.

The callback adds a one-time login notice to the configured destination. The root authentication notice displays the localised successful-login toast and immediately removes that query parameter from the URL. Subscription enforcement is separate: `BILLING_ACCESS.REQUIRED: false` prevents authentication from detouring to `BILLING_ACCESS.REDIRECT_PATH`.

See [Login redirects and subscription paywalls](./login-redirects-and-paywalling.md) for the exact callback order, the difference between callback gating and a complete paywall, and configuration examples.

## Billing configuration

```ts
BILLING: {
  AUTOMATIC_TAX: false,
  BILLING_ADDRESS_COLLECTION: 'auto',
  ALLOW_PROMOTION_CODES: true,
},
BILLING_ACCESS: {
  REQUIRED: true,
  FEATURE_LOOKUP_KEY: null,
  REDIRECT_PATH: '/account/billing/subscribe?full=1',
},
```

- `AUTOMATIC_TAX` asks Stripe to calculate tax during Checkout. Stripe registrations and Product tax codes must also be configured.
- `BILLING_ADDRESS_COLLECTION` is `auto` or `required`.
- `ALLOW_PROMOTION_CODES` controls Stripe promotion-code entry.
- `REQUIRED` controls whether an authenticated user without the configured entitlement is redirected before reaching the normal login destination. Set it to `false` when authentication must not require a subscription.
- `FEATURE_LOOKUP_KEY` authorises through the projected entitlement with that stable key. `null` retains the compatibility rule of any active/trialling Subscription.
- `REDIRECT_PATH` is used when required billing access is absent.

In the current core, this billing check runs in the magic-link/social callback and in full-app layouts through `requireAppAccess()`. Password sign-in does not pass through that callback, so its destination must inherit the correct server layout. Proxy remains claims-only. Put billing acquisition beneath `requireOnboardedUser()` so a user without access can reach it, and protect paid APIs, Server Actions, and data with independent server-side entitlement checks. See [Login redirects and subscription paywalls](./login-redirects-and-paywalling.md).

Payment methods are not listed in code. Configure Dynamic Payment Methods in Stripe Dashboard.

`BILLING_ACCESS` is the complete current billing-access configuration contract. Existing applications must remove the obsolete `ACCOUNT_FORCE_SUBSCRIPTION` and `ACCOUNT_ENFORCE_SUBSCRIPTION_PATH` properties from their developer-owned configuration before adopting this Core version; `supacharger doctor` reports them but does not rewrite the file.

## Authentication methods

```ts
AUTHENTICATION: {
  EMAIL_PASSWORD: { SIGN_IN: true, SIGN_UP: true },
  PASSWORDLESS_EMAIL: {
    SIGN_IN: 'otp',
    SIGN_UP: 'disabled',
    OTP_LENGTH: 6,
  },
  SIGN_UP_EMAIL_VERIFICATION: 'otp',
  MFA_TOTP: { REQUIRED_FOR_SIGN_IN: false },
},
```

`EMAIL_PASSWORD` controls password actions independently. `PASSWORDLESS_EMAIL.SIGN_IN` and `SIGN_UP` each accept one exclusive mode: `disabled`, `otp`, or `link`. Sign-in always uses `shouldCreateUser: false`. `OTP_LENGTH` accepts 6 through 10 and controls the rendered fields; keep it equal to local `[auth.email] otp_length` and the hosted Supabase setting. `SIGN_UP_EMAIL_VERIFICATION` is separate from passwordless login and accepts `disabled`, `otp`, `link`, or `otp-and-link`. Managed TOTP enrolment is always available in Account Security. `REQUIRED_FOR_SIGN_IN` challenges enrolled AAL1 sessions before the final sign-in destination. See [Account security and TOTP MFA](./mfa-and-security.md).

## Mobile deep-link configuration

```ts
MOBILE_DEEP_LINKING: {
  ENABLED: false,
  ASSOCIATED_PATHS: [
    '/auth/callback',
    '/auth/confirm',
  ],
  IOS: { APP_IDS: [] },
  ANDROID: { APPS: [] },
},
```

Enable this only after the production HTTPS domain and signed native identifiers are ready. `IOS.APP_IDS` contains Apple App ID prefix and bundle identifier pairs. Each `ANDROID.APPS` entry contains a package name plus one or more uppercase SHA-256 signing-certificate fingerprints. Supacharger generates the platform well-known association responses; the native applications still declare and validate the matching hosts and paths. See [Mobile login verification with deep links](./mobile-auth-deep-linking.md).

## Profile identity and onboarding

```ts
PROFILE_IDENTITY: {
  USERNAME: 'disabled',
  AVATAR: 'optional',
  HEADER_IMAGE: 'optional',
},
POST_SIGN_IN_ONBOARDING: {
  REQUIRED: true,
  REDIRECT_PATH: '/account/setup-profile',
},
```

`USERNAME` accepts `disabled`, `optional`, or `required`. The database field remains installed and nullable in every mode. Disabled removes it from shared forms, username routes, and identity display. Optional accepts blank. Required adds it to completion.

`AVATAR` and `HEADER_IMAGE` accept `disabled` or `optional` and control their managed account media fields. Storage remains installed so the policy can change without rewriting migration history. See [Account settings](./account-settings.md) for the full settings contract and extension seams.

When onboarding is required, the callback and protected server layouts call `api.is_profile_complete_by_current_user(input_username_required)` and redirect users whose required fields are missing. Proxy performs no profile or billing RPC. `REDIRECT_PATH` is application-owned and must point to a real setup page beneath `requireVerifiedUser()`, outside the onboarding guard it recovers. Core ships `/account/setup-profile`; applications may retain richer product-specific UI at their configured path.

This setting controls routing only. Supabase Auth triggers create and synchronise `app.profiles` for every user even when enforcement is false.

## Organisations

```ts
ORGANISATIONS: {
  ENABLED: false,
  AUTHENTICATION_HANDLE: 'disabled',
  CHOOSER_PATH: '/account/organisation',
  ROUTE_MODE: 'root-handle',
  PROFILE_MEDIA: true,
},
```

Organisation tables and service adapters remain installed when disabled. `AUTHENTICATION_HANDLE` accepts `disabled`, `optional`, or `required`, and applies only when organisations are enabled. Selection occurs after authentication; creation belongs in authenticated onboarding. Applications must not treat the handle as untrusted Auth metadata.

## Other settings

Branding such as `SITE_TITLE`, document metadata, root-provider switches, analytics, authentication providers, route guards, redirects, password policy, locale configuration, and toast presentation also belong to the developer-owned configuration seam. Use the existing typed values and keep application-specific policy out of CLI-managed modules.
